package com.caiguoping.yuvconvert;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.media.ImageReader;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.caiguoping.javayuv.Test2;
import com.caiguoping.yuv.Test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, Camera.PreviewCallback, View.OnClickListener {
    private static final String TAG = "MainActivity";
    private SurfaceView surfaceView;
    private Camera camera;
    private boolean show;
    private byte[] bytes;
    private HandlerThread handlerThread;
    private Handler loopHandler;
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        surfaceView = findViewById(R.id.surface_view);
        surfaceView.getHolder().addCallback(this);
        surfaceView.setOnClickListener(this);

        handlerThread = new HandlerThread("Image_Thread");
        handlerThread.start();
        loopHandler = new Handler(handlerThread.getLooper());

        imageView = findViewById(R.id.image);
        imageView.setOnClickListener(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 0);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (camera != null) {
            camera.stopPreview();
            camera.setPreviewCallback(null);
            camera.release();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            try {
                int w = 1280;
                int h = 720;

                camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                Camera.Parameters parameters = camera.getParameters();
                parameters.setPreviewSize(w, h);
                parameters.setPreviewFormat(ImageFormat.NV21);
                camera.setParameters(parameters);
                camera.setPreviewDisplay(surfaceView.getHolder());
                camera.setPreviewCallback(this);
                camera.startPreview();

                bytes = new byte[parameters.getPreviewSize().width
                        * parameters.getPreviewSize().height * ImageFormat.getBitsPerPixel(parameters.getPreviewFormat()) / 8];

                ViewGroup.LayoutParams layoutParams = surfaceView.getLayoutParams();
                layoutParams.width = w / 6;
                layoutParams.height = h / 6;
                surfaceView.setLayoutParams(layoutParams);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        if (show) {
            show = false;
            System.arraycopy(data, 0, bytes, 0, data.length);
            Camera.Size size = camera.getParameters().getPreviewSize();
            loopHandler.post(() -> {
                int w = size.width;
                int h = size.height;

/*                byte[] i420 = new byte[w * h * 12 / 8];
                Test.NV21ToI420(w, h, bytes, i420);

                int rotate = 0;
                byte[] dst = new byte[w * h * 12 / 8];
                Test.I420Rotate(w, h, bytes, dst, rotate);
                switch (rotate) {
                    case 90:
                    case 270:
                        int tmp = h;
                        h = w;
                        w = tmp;
                        break;
                }*/
                byte[] abgr = new byte[w * h * 4];

                long start = SystemClock.elapsedRealtime();
                Test.NV21ToABGR(w, h, bytes, abgr);
//                Test.I420ToABGR(w, h, dst, abgr);
//                Test2.NV21ToABGR(w, h, bytes, abgr);

                Log.d(TAG, "onPreviewFrame: " + (SystemClock.elapsedRealtime() - start) + "ms");

                Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
                bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(abgr));
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        imageView.setImageBitmap(bitmap);
                    }
                });
            });
        }
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.surface_view) {
            show = true;
        } else if (id == R.id.image) {
            loopHandler.post(() -> {

                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.e);
                int w = bitmap.getWidth();
                int h = bitmap.getHeight();
                byte[] array = new byte[bitmap.getByteCount()];
                bitmap.copyPixelsToBuffer(ByteBuffer.wrap(array));
                bitmap.recycle();

//                byte[] nv21 = Test.createByteBuff(w, h, Test.FORMAT_NV21);
//                Test2.ABGRToNV21(w, h, array, nv21);
//                Test.bitmapToNv21(bitmap, nv21);
//                bitmap.recycle();

                byte[] abgr = Test.createByteBuff(w, h, Test.FORMAT_ARGB_8888);
//                Test2.NV21ToABGR(w, h, nv21, abgr);
//                Test2.NV21ToABGR(w, h, nv21, abgr);

                Test.ARGBRotate(w, h, array, abgr, 90);

                Bitmap _bitmap = Bitmap.createBitmap(h, w, Bitmap.Config.ARGB_8888);
                _bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(abgr));
                runOnUiThread(() -> {
                    imageView.setImageBitmap(_bitmap);
                });
            });
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handlerThread.quit();
    }
}